using System;
using System.Collections.Generic;
using UnityEngine;

namespace DL
{
    /// <summary>
    /// 全局黑板系统
    /// </summary>
    public class GameBlackboardGlobal : Singleton<GameBlackboardGlobal>
    {
        private Dictionary<string, GameBlackboardKey> m_KeyRegistry = new();
        private Dictionary<GameBlackboardKey, object> m_Emtries = new();

        public T Get<T>(string keyName)
        {
            var key = GetOrRegistry(keyName);
            if (!TryGetValue<T>(key, out T value))
            {
                Debug.LogWarning($"Key:{key}还没有被存储，返回默认值");
            }
            return value;
        }

        public void Set<T>(string keyName,T value)
        {
            var key = GetOrRegistry(keyName);
            SetValue(key, value);
        }

        public void Remove(string keyName)
        {
            var key = GetOrRegistry(keyName);
            if (ContainsKey(key))
            {
                Remove(key);
            }
            m_KeyRegistry.Remove(keyName);
        }
    

        private GameBlackboardKey GetOrRegistry(string keyName)
        {
            if (string.IsNullOrEmpty(keyName))
            {
                // UnityEngine.Debug.LogError("keyName is NullOrEmpty!");
                throw new ArgumentException("keyName is NullOrEmpty!");
            }

            if (!m_KeyRegistry.TryGetValue(keyName, out var hash))
            {
                hash = new GameBlackboardKey(keyName);
                m_KeyRegistry.Add(keyName, hash);
            }
            return hash;
        }

        private bool ContainsKey(GameBlackboardKey key) => m_Emtries.ContainsKey(key);
        
        private bool Remove(GameBlackboardKey key) => m_Emtries.Remove(key);
        
        private bool TryGetValue<T>(GameBlackboardKey key, out T value)
        {
            if (m_Emtries.TryGetValue(key, out var entry) && entry is BlackboardEntry<T> castedEntry)
            {
                value = castedEntry.Value;
                return true;
            }
            
            value = default;
            return false;
        }

        private void SetValue<T>(GameBlackboardKey key, T value)
        {
            m_Emtries[key] = new BlackboardEntry<T>(key, value);
        }
    }
}
